package one.stand.handler;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.HashedWheelTimer;
import one.stand.config.NettyConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 */
@Component
public class ChildHandler extends ChannelInitializer<SocketChannel> {
    /**
     * 数据处理
     */
    @Autowired
    ServerHandler serverHandler;

    @Value("${netty.ssl_password}")
    private String sslPassword;
    @Value("${netty.ssl_file_name}")
    private String sslFileName;
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        Resource resource = new ClassPathResource(sslFileName);
        SSLContext sslContext = createSSLContext("JKS", resource.getInputStream(), sslPassword);
        //SSLEngine 此类允许使用ssl安全套接层协议进行安全通信
        SSLEngine engine = sslContext.createSSLEngine();
        engine.setUseClientMode(false);

        ChannelPipeline p = socketChannel.pipeline();
        p.addLast("sslHandler",new SslHandler(engine));
        //websocket协议本身是基于http协议的，所以这边也要使用http解编码器
        p.addLast("http-codec", new HttpServerCodec());
        //对写大数据流的支持
        p.addLast("http-chunked", new ChunkedWriteHandler());
        //几乎在Netty中的编程都会使用到这个handler
        p.addLast("aggregator", new HttpObjectAggregator(1024 * 64));
        //websocket地址
        p.addLast("webSocketServerProtocolHandler", new WebSocketServerProtocolHandler("/ws"));

        p.addLast(serverHandler);
    }


    public static SSLContext createSSLContext(String type, InputStream ksInputStream, String password) throws Exception {
        // "JKS"
        KeyStore ks = KeyStore.getInstance(type);
        ks.load(ksInputStream, password.toCharArray());
        //KeyManagerFactory充当基于密钥内容源的密钥管理器的工厂。
        //getDefaultAlgorithm:获取默认的 KeyManagerFactory 算法名称。
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, password.toCharArray());
        //SSLContext的实例表示安全套接字协议的实现，它充当用于安全套接字工厂或 SSLEngine 的工厂。
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);
        return sslContext;
    }

}
